package cn.edu.bupt.freewings.forum.client.base;

import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.HttpURLConnection;
import org.apache.commons.httpclient.HttpException;
import org.apache.commons.httpclient.HttpMethod;
import org.apache.commons.httpclient.HttpConnectionManager;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.MultiThreadedHttpConnectionManager;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.methods.PutMethod;
import org.apache.commons.httpclient.methods.DeleteMethod;
import org.apache.commons.httpclient.methods.ByteArrayRequestEntity;
import org.apache.log4j.Logger;
import com.google.protobuf.Message;

public class ClientUtility {

	private static Logger logger = Logger.getLogger(ClientUtility.class);

	public enum HTTPMethod {
		GET, POST, PUT, DELETE
	}

	static MultiThreadedHttpConnectionManager connectionManager;
	static int CONNECTION_TIME_OUT = 2000;
	static int CONNECTION_MANAGER_TIME_OUT = 2000;
	static HttpClient httpClient;
	static {
		connectionManager = new MultiThreadedHttpConnectionManager();
		connectionManager.getParams().setConnectionTimeout(CONNECTION_TIME_OUT);
		connectionManager.getParams().setDefaultMaxConnectionsPerHost(
				Integer.MAX_VALUE);
		connectionManager.getParams().setMaxTotalConnections(Integer.MAX_VALUE);
		httpClient = new HttpClient(connectionManager);
		httpClient.getParams().setConnectionManagerTimeout(
				CONNECTION_MANAGER_TIME_OUT);
	}

	public static HttpMethod getHttpMethod(HTTPMethod method, String url,
			byte[] content) {
		switch (method) {
		case GET:
			return new GetMethod(url);
		case DELETE:
			return new DeleteMethod(url);
		case POST:
			PostMethod postMethod = new PostMethod(url);
			postMethod.setRequestEntity(new ByteArrayRequestEntity(content));
			return postMethod;
		case PUT:
			PutMethod putMethod = new PutMethod(url);
			putMethod.setRequestEntity(new ByteArrayRequestEntity(content));
			return putMethod;
		}
		throw new IllegalArgumentException("HttpMethod not found");
	}

	public static Message makeHttpRequest(HTTPMethod method, String url,
			String contentType, byte[] content, String accept, Class<?> returnClass) {
		HttpMethod httpMethod = getHttpMethod(method, url, content);
		if (contentType != null) {
			httpMethod.addRequestHeader("Content-Type", contentType);
		}

		if (accept != null) {
			httpMethod.addRequestHeader("accept", accept);
		}

		Message msg = null;

		try {
			int responseCode;
			long time = System.currentTimeMillis();
			responseCode = httpClient.executeMethod(httpMethod);
			logger.info("" + (System.currentTimeMillis() - time) + "ms "
					+ httpMethod.getName() + " " + httpMethod.getURI());
			if (responseCode != HttpURLConnection.HTTP_NO_CONTENT) {
				InputStream responseStream = httpMethod.getResponseBodyAsStream();
				Method parseMethod = returnClass.getMethod("parseFrom",
						InputStream.class);
				msg = (Message) parseMethod.invoke(null, responseStream);
			}
		} catch (HttpException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (SecurityException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (NoSuchMethodException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} finally {
			httpMethod.releaseConnection();
		}
		return msg;
	}
}
